package org.liaohailong.helloworld.leetcode;

import java.util.Stack;

/**
 * Author: liaohailong
 * Time: 2021/4/26 17:10
 * Describe:
 */
public class LeetCode2 {
    public static void main(String[] args) {
        ListNode l1 = create(new int[]{2, 4, 9});
        ListNode l2 = create(new int[]{5, 6, 4, 9});
        ListNode listNode = addTwoNumbers(l1, l2);

        printNode(l1);
        printNode(l2);
        printNode(listNode);
    }

    private static void printNode(ListNode head) {
        ListNode node = head;
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        while (node != null) {
            sb.append(node.val);
            sb.append(",");
            node = node.next;
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append("]");
        System.out.println(sb.toString());
    }

    private static ListNode create(int[] arr) {
        ListNode head = null;
        ListNode node = null;
        for (int i : arr) {
            if (head == null) {
                head = new ListNode(i);
                node = head;
            } else {
                node.next = new ListNode(i);
                node = node.next;
            }
        }
        return head;
    }


    //    输入：l1 = [2,4,3], l2 = [5,6,4]
    //    输出：[7,0,8]
    //    解释：342 + 465 = 807.
    public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head1 = reserve(l1);
        ListNode head2 = reserve(l2);
        ListNode[] balance = balance(head1, head2);
        head1 = balance[0];
        head2 = balance[1];

        ListNode n1 = reserve(head1);
        ListNode n2 = reserve(head2);

        ListNode resultHead = null;
        ListNode resultNode = null;
        int extra = 0;
        while (n1 != null || n2 != null) {
            int n1Val = n1 == null ? 0 : n1.val;
            int n2Val = n2 == null ? 0 : n2.val;
            int plus = n1Val + n2Val;
            if (plus >= 10) {
                if (resultHead != null) {
                    plus += extra;
                    extra = 0;
                    if (plus >= 10) extra = (int) (plus / 10f);
                } else {
                    extra = (int) (plus / 10f);
                }
                plus = plus % 10;
            } else if (extra > 0) {
                plus += extra;
                extra = 0;
                if (plus >= 10) extra = (int) (plus / 10f);
                plus = plus % 10;
            }

            if (resultHead == null) {
                resultHead = new ListNode(plus);
                resultNode = resultHead;
            } else {
                resultNode.next = new ListNode(plus);
                resultNode = resultNode.next;
            }

            n1 = n1 != null ? n1.next : null;
            n2 = n2 != null ? n2.next : null;
        }

        if (extra > 0) {
            resultNode.next = new ListNode(extra);
        }
        return resultHead;
    }

    private static ListNode[] balance(ListNode l1, ListNode l2) {
        int size1 = size(l1);
        int size2 = size(l2);
        int offset = Math.abs(size1 - size2);
        if (size1 > size2) {
            while (offset > 0) {
                ListNode head = new ListNode(0);
                head.next = l2;
                l2 = head;
                offset--;
            }
        } else if (size1 < size2) {
            while (offset > 0) {
                ListNode head = new ListNode(0);
                head.next = l1;
                l1 = head;
                offset--;
            }
        }

        return new ListNode[]{l1, l2};
    }

    private static int size(ListNode head) {
        int count = 1;
        ListNode node = head;
        while (node != null) {
            count++;
            node = node.next;
        }
        return count;
    }

    public static ListNode reserve(ListNode head) {
        Stack<Integer> stack = new Stack<>();
        ListNode node = head;
        while (node != null) {
            stack.push(node.val);
            node = node.next;
        }

        head = null;
        node = null;
        while (!stack.isEmpty()) {
            Integer top = stack.pop();
            if (head == null) {
                head = new ListNode(top);
                node = head;
            } else {
                node.next = new ListNode(top);
                node = node.next;
            }
        }
        return head;
    }


    public static class ListNode {
        int val;
        ListNode next;

        ListNode() {
        }

        ListNode(int val) {
            this.val = val;
        }

        ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
        }
    }
}
